home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianLVR5000.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  11KB  |  523 lines

  1. /*ScianLVR5000.c
  2.   Eric Pepke
  3.   Controls the LVR5000 video recorder
  4.  
  5.   This file controls the Sony LVR-5000 videodisc recorder.  It may be able 
  6.   to control other models in the Sony line as well, but this is the only one
  7.   that we have.  It currently runs only on the Silicon Graphics IRIS 
  8.   workstation, but should be easy to make run on other systems.
  9.  
  10.   To make this recorder work, you need to get a video signal from the 
  11.   workstation to the recorder, and connect the recorder to the workstation
  12.   via a serial port.  
  13.  
  14.   The video signal can either be the standard IRIS RGB signal run through 
  15.   a scan converter, or the direct IRIS RGB output when the IRIS is set to
  16.   "NTSC" mode.  Don't hook the high-resolution output directly to the 
  17.   recorder ever!  The recorder tries to sync with the incoming signal, and
  18.   that can't be good for the servos.
  19.  
  20.   The serial signal can go to any port on the back of the IRIS.  The default 
  21.   port which is used is gotten from the environment variable SCIAN_RECORDER_DEV.
  22.   If that environment variable is not present, then the #define'd value
  23.   of LVR5000_DEV from ScianLVR5000.h is used.  The port is set to 9600 baud
  24.   by default.  This can all be changed via the control panel of the recorder.
  25.  
  26.   Oh, yes.  In order for the machine to work, the LVR-5000 has to be set to
  27.   "Remote" operation via the front panel.
  28.  
  29.   Thanks to Roland Schweitzer for the idea of using an environment variable
  30.   as an interim solution.
  31. */
  32.  
  33. #include "Scian.h"
  34. #include "ScianTypes.h"
  35. #include "ScianWindows.h"
  36. #include "ScianDialogs.h"
  37. #include "ScianIDs.h"
  38. #include "ScianLVR5000.h"
  39. #include "ScianErrors.h"
  40. #include "ScianColors.h"
  41. #include "ScianRecorders.h"
  42.  
  43. #ifdef TERMIO
  44.  
  45. /*Timeout in seconds*/
  46. #define LVRTIMEOUT        5
  47.  
  48. /*Retries*/
  49. #define NRETRIES    3
  50.  
  51. int debug = 0;
  52.  
  53. static ObjPtr ConnectLVR5000();
  54.  
  55. /*Internal prototypes*/
  56. #ifdef PROTO
  57. static void SendPort(int, char);
  58. static int OpenPort(char *, int);
  59. static int SendCmd(int, int);
  60. static int WaitForResponse(int);
  61. static int WaitALongTimeForResponse(int);
  62. static int Read5Digits(int);
  63. static Bool WaitForCompletion(int);
  64. static int SendNumber(int, int);
  65. #endif
  66.  
  67. #ifdef PROTO
  68. static void SendPort(int portDev, char c)
  69. #else
  70. static void SendPort(portDev, c)
  71. int portDev;
  72. char c;
  73. #endif
  74. {
  75.     write(portDev, &c, 1);
  76. }
  77.  
  78. #ifdef PROTO
  79. static int OpenPort(char *devName, int baudRate)
  80. #else
  81. static int OpenPort(devName, baudRate)
  82. char *devName;
  83. int baudRate;
  84. #endif
  85. /*Opens a port to the recorder, returns it if successful*/
  86. {
  87.     int portDev;
  88.     struct termio ioStuff;
  89.     ObjPtr var;
  90.  
  91.     portDev = open(devName, O_RDWR | O_NDELAY | O_EXCL);
  92.     if (portDev < 0)
  93.     {
  94.     return portDev;
  95.     }
  96.     ioctl(portDev, TCGETA, &ioStuff);
  97.     ioStuff . c_oflag = 0;
  98.     ioStuff . c_iflag = IGNBRK;
  99.     ioStuff . c_lflag = 0;
  100.  
  101.     /*Make cflag from baud rate*/
  102.     switch(baudRate)
  103.     {
  104.     case RB_300:
  105.         ioStuff . c_cflag = (unsigned short) (B300 | CS8 | CLOCAL | CREAD | CSTOPB);
  106.         break;
  107.     case RB_1200:
  108.         ioStuff . c_cflag = (unsigned short) (B1200 | CS8 | CLOCAL | CREAD);
  109.         break;
  110.     case RB_2400:
  111.         ioStuff . c_cflag = (unsigned short) (B2400 | CS8 | CLOCAL | CREAD);
  112.         break;
  113.     case RB_4800:
  114.         ioStuff . c_cflag = (unsigned short) (B4800 | CS8 | CLOCAL | CREAD);
  115.         break;
  116.     case RB_9600:
  117.         ioStuff . c_cflag = (unsigned short) (B9600 | CS8 | CLOCAL | CREAD);
  118.         break;
  119.     case RB_19200:
  120.         ioStuff . c_cflag = (unsigned short) (B19200 | CS8 | CLOCAL | CREAD);
  121.         break;
  122.     }
  123.  
  124.     ioStuff . c_cc[4] = 1;
  125.     ioStuff . c_cc[0] = 1;
  126.  
  127.     ioctl(portDev, TCSETA, &ioStuff);
  128.     return portDev;
  129. }
  130.  
  131. static int SendCmd(portDev, number)
  132. int portDev;
  133. int number;
  134. /*Sends out command name with number.  Returns true iff successful*/
  135. {
  136.     int response; 
  137.     
  138.     SendPort(portDev, number);
  139.     response = WaitForResponse(portDev);
  140.  
  141.     switch (response)
  142.     {
  143.     case ACK:
  144.         return true;
  145.     case NAK:
  146.         return false;
  147.     case -1:
  148.         return false;
  149.     default:
  150.         return false;
  151.     }
  152. }
  153.  
  154. static int WaitForResponse(portDev)
  155. int portDev;
  156. /*Waits for a response from the sony and returns it or -1 if it timed out
  157.   or is closed*/
  158. {
  159.     char retVal;
  160.     long startTime, curTime;
  161.     struct tms buffer;
  162.  
  163.     startTime = times(&buffer);
  164.     do
  165.     {
  166.     if (read(portDev, &retVal, 1))
  167.     {
  168.         return retVal;
  169.     }
  170.     curTime = times(&buffer);
  171.     } while (curTime < startTime + LVRTIMEOUT * HEARTBEAT);
  172.     return -1;
  173. }
  174.  
  175. static int WaitALongTimeForResponse(portDev)
  176. int portDev;
  177. /*Waits a long time for a response from the sony and returns it or -1 if it 
  178.   timed out or is closed*/
  179. {
  180.     char retVal;
  181.     long startTime, curTime;
  182.     struct tms buffer;
  183.  
  184.     startTime = times(&buffer);
  185.     do
  186.     {
  187.     if (read(portDev, &retVal, 1))
  188.     {
  189.         return retVal;
  190.     }
  191.     curTime = times(&buffer);
  192.     } while (curTime < startTime + 400 * HEARTBEAT);
  193.     return -1;
  194. }
  195.  
  196. #if 0
  197. int GetStatus(status)
  198. char status[5];
  199. /*Gets a status from the recorder and returns it in status.  Returns true iff
  200.   successful*/
  201. {
  202.     long startTime, curTime;
  203.     struct tms buffer;
  204.     int k;
  205.     char stat;
  206.  
  207.     SendPort(STATUS_INQ);
  208.     
  209.     for (k = 0; k < 5; ++k)
  210.     {
  211.     startTime = times(&buffer);
  212.     do
  213.     {
  214.         if (read(portDev, &stat, 1))
  215.         {
  216.             status[k] = stat;
  217.             goto oneMore;
  218.         }
  219.         curTime = times(&buffer);
  220.     } while (curTime < startTime + LVRTIMEOUT * HEARTBEAT);
  221.     return 0;
  222. oneMore:;
  223.     }
  224.     return 1;
  225. }
  226. #endif
  227.  
  228. static ObjPtr ConnectLVR5000(object)
  229. ObjPtr object;
  230. /*Connects to the LVR5000.  Returns true iff successful*/
  231. {
  232.     int portDev;
  233.     int k;
  234.     ObjPtr var;
  235.     char *devName;
  236.     int baudRate;
  237.  
  238.     MakeVar(object, PORTDEV);
  239.     var = GetStringVar("ConnectLVR5000", object, PORTDEV);
  240.     if (var)
  241.     {
  242.     devName = GetString(var);
  243.     }
  244.     else
  245.     {
  246.     devName = LVR5000_DEV;
  247.     }
  248.  
  249.     MakeVar(object, BAUDRATE);
  250.     var = GetIntVar("ConnectTQ2026F", object, BAUDRATE);
  251.     if (var)
  252.     {
  253.     baudRate = GetInt(var);
  254.     }
  255.     else
  256.     {
  257.     baudRate = RB_9600;
  258.     }
  259.  
  260.     /*Open a port*/
  261.     portDev = OpenPort(devName, baudRate);
  262.     if (portDev < 0)
  263.     {
  264.     return ObjFalse;
  265.     }
  266.  
  267.     /*Now that a port is open, connect to it*/
  268.     for (k = 0; k < NRETRIES; ++k)
  269.     {
  270.     if (SendCmd(portDev, CONNECT_TO_PROCESSOR))
  271.     {
  272.         SendCmd(portDev, COLOR_MODE);
  273.         SendCmd(portDev, NTSC_MODE);
  274.         SendCmd(portDev, ALL_CLEAR);
  275.         SendCmd(portDev, FRAME_NO_MODE);
  276.         SetVar(object, PORTNUMBER, NewInt(portDev));
  277.         return ObjTrue;
  278.     }
  279.     }
  280.     close(portDev);
  281.     return ObjFalse;
  282. }
  283.  
  284. static int Read5Digits(portDev)
  285. int portDev;
  286. /*Reads a five digit integer from portDev.  Returns -1 on timeout*/
  287. {
  288.     int k;
  289.     int cum;
  290.  
  291.     cum = 0;
  292.     for (k = 0; k < 5; ++k)
  293.     {
  294.     int digit;
  295.     digit = WaitForResponse(portDev);
  296.     if (digit >= '0' && digit <= '9')
  297.     {
  298.         cum = cum * 10 + digit - '0';
  299.     }
  300.     else
  301.     {
  302.         return -1;
  303.     }
  304.     }
  305.     return cum;
  306. }
  307.  
  308. static int SendNumber(portDev, num)
  309. int portDev;
  310. int num;
  311. /*Sends a number followed by ENTER to the recorder*/
  312. {
  313.     char numStr[10];
  314.     int k;
  315.  
  316.     sprintf(numStr, "%d", num);
  317.     for (k = 0; numStr[k]; ++k)
  318.     {
  319.     if (!SendCmd(portDev, numStr[k])) return false;
  320.     }
  321.     return SendCmd(portDev, ENTER);
  322. }
  323.  
  324. static Bool WaitForCompletion(portDev)
  325. int portDev;
  326. {
  327.     if (WaitALongTimeForResponse(portDev) == COMPLETION)
  328.     {
  329.     return true;
  330.     }
  331.     else
  332.     {
  333.     return false;
  334.     }
  335. }
  336.  
  337. static ObjPtr PrepareToRecordLVR5000(object, nFrames)
  338. ObjPtr object;
  339. long nFrames;
  340. /*Prepares to record nFrames on an LVR5000.  Returns true iff successful.*/
  341. {
  342.     ObjPtr port;
  343.  
  344.     port = GetVar(object, PORTNUMBER);
  345.     if (port)
  346.     {
  347.     int portDev;
  348.     int begin, end, firstBegin;
  349.     int k;
  350.  
  351.     portDev = GetInt(port);
  352.  
  353.     /*Search for blank area and go to record standby*/
  354.     for (k = 0; k < NRETRIES; ++k)
  355.     {
  356.         SendCmd(portDev, REC_STANDBY);
  357.         if (WaitForCompletion(portDev))
  358.         {
  359.         goto okbud;
  360.         }
  361.         ReportError("PrepareToRecordLVR5000", "REC_STANDBY did not complete");
  362.     }
  363.     return ObjFalse;
  364. okbud:
  365.     /*Get first blank area*/
  366.     SendPort(portDev, CURRENT_BLANK_INQ);
  367.     firstBegin = begin = Read5Digits(portDev);
  368.     if (begin < 0) return ObjFalse;
  369.     end = Read5Digits(portDev);
  370.     if (end < 0) return ObjFalse;
  371.  
  372.     /*If not enough, search for more*/
  373.     if (end - begin <= nFrames)
  374.     {
  375.         do
  376.         {
  377.         if (SendCmd(portDev, EDGE_RIGHT))
  378.         {
  379.             if (WaitForCompletion(portDev))
  380.             {
  381.             SendPort(portDev, CURRENT_BLANK_INQ);
  382.             begin = Read5Digits(portDev);
  383.             if (begin < 0) return ObjFalse;
  384.             end = Read5Digits(portDev);
  385.             if (end < 0) return ObjFalse;
  386.             }
  387.             else
  388.             {
  389.             ReportError("PrepareToRecordLVR5000", "EDGE_RIGHT did not complete");
  390.             return ObjFalse;
  391.             }
  392.         }
  393.         else
  394.         {
  395.             ReportError("PrepareToRecordLVR5000", "EDGE_RIGHT did not complete");
  396.             return ObjFalse;
  397.         }
  398.         } while (begin != firstBegin && end - begin <= nFrames);
  399.  
  400.         if (end - begin <= nFrames)
  401.         {
  402.         ReportError("PrepareToRecordLVR5000", "There is not enough space on the disc");
  403.         return ObjFalse;
  404.         }
  405.     }
  406.  
  407.     /*Say for the range we need*/
  408.     SendNumber(portDev, begin);
  409.     SendNumber(portDev, begin + nFrames);
  410.     SendCmd(portDev, ENTER);
  411.     if (!WaitForCompletion(portDev))
  412.     {
  413.         return ObjFalse;
  414.     }
  415.     SendCmd(portDev, FRAME_REC);
  416.  
  417.     return ObjTrue;
  418.     }
  419.     else
  420.     {
  421.     return ObjFalse;
  422.     }
  423. }
  424.  
  425. static ObjPtr StopRecordingLVR5000(object)
  426. ObjPtr object;
  427. /*Stops recording*/
  428. {
  429.     ObjPtr port;
  430.  
  431.     port = GetVar(object, PORTNUMBER);
  432.     if (port)
  433.     {
  434.     int portDev;
  435.     portDev = GetInt(port);
  436.  
  437.     SendCmd(portDev, ALL_CLEAR);
  438.     return ObjTrue;
  439.     }
  440.     else
  441.     {
  442.     return ObjFalse;
  443.     }
  444. }
  445.  
  446. static ObjPtr DisconnectLVR5000(object)
  447. ObjPtr object;
  448. {
  449.     int portDev;
  450.     ObjPtr port;
  451.  
  452.     port = GetVar(object, PORTNUMBER);
  453.     if (port)
  454.     {
  455.     portDev = GetInt(port);
  456.     close(portDev);
  457.     SetVar(object, PORTNUMBER, NULLOBJ);
  458.     }
  459.     return ObjTrue;
  460. }
  461.  
  462. static ObjPtr SnapOneFrameLVR5000(object)
  463. ObjPtr object;
  464. {
  465.     int portDev;
  466.     int test;
  467.     ObjPtr port;
  468.  
  469.     port = GetVar(object, PORTNUMBER);
  470.     if (port)
  471.     {
  472.     portDev = GetInt(port);
  473.     test = SendCmd(portDev, REC);
  474.     if (!WaitForCompletion(portDev))
  475.     {
  476.         return ObjFalse;
  477.     }
  478.     return test ? ObjTrue : ObjFalse;
  479.     }
  480.     else
  481.     {
  482.     return ObjTrue;
  483.     }
  484. }
  485. #endif
  486.  
  487. #ifdef PROTO
  488. void InitLVR5000(void)
  489. #else
  490. void InitLVR5000()
  491. #endif
  492. /*Create a new LVR-5000 object*/
  493. {
  494. #ifdef TERMIO
  495.     ObjPtr recorder;
  496.     char *devName;
  497.  
  498.     recorder = NewRecorder(commRecorderClass, "LVR-5000", "Sony");
  499.     SetMethod(recorder, CONNECT, ConnectLVR5000);
  500.     SetMethod(recorder, DISCONNECT, DisconnectLVR5000);
  501.     SetMethod(recorder, PREPARETORECORD, PrepareToRecordLVR5000);
  502.     SetMethod(recorder, STOPRECORDING, StopRecordingLVR5000);
  503.     SetMethod(recorder, SNAPONEFRAME, SnapOneFrameLVR5000);
  504.  
  505.     devName = getenv("SCIAN_RECORDER_DEV");
  506.     if (!devName || !devName[0])
  507.     {
  508.     devName = LVR5000_DEV;
  509.     }
  510.     SetVar(recorder, PORTDEV, NewString(devName));
  511.  
  512.     RegisterRecorder(recorder);
  513. #endif
  514. }
  515.  
  516. #ifdef PROTO
  517. void KillLVR5000(void)
  518. #else
  519. void KillLVR5000()
  520. #endif
  521. {
  522. }
  523.